<!DOCTYPE html>
<html>
<head>
    <title>Web白噪音生成器</title>
    <style>
        .container { padding: 20px; max-width: 600px; margin: 0 auto; }
        .controls { margin: 20px 0; }
        .slider { width: 200px; vertical-align: middle; }
        #visualizer { 
            width: 100%; 
            height: 100px;
            background: linear-gradient(#e0e0e0, #f5f5f5);
            margin: 20px 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <h2>网页版白噪音生成器</h2>
        
        <!-- 音频可视化画布 -->
        <canvas id="visualizer"></canvas>

        <!-- 控制面板 -->
        <div class="controls">
            <button onclick="toggleNoise()">▶️ 启动/暂停</button>
            <br>
            <label>音量调节: 
                <input type="range" class="slider" id="volume" 
                       min="0" max="1" step="0.1" value="0.5" 
                       oninput="(this.value)">
            </label>
            <span id="volumeValue">50%</span>
        </div>

        <!-- 核心音频处理脚本 -->
        <script>
            let audioContext, noiseNode, analyser;
            let isPlaying = false;

            // 初始化音频环境
            function initAudio() {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
                analyser = audioContext.createAnalyser();
                analyser.fftSize = 256;
            }

            // 生成白噪音
            function createNoise() {
                const bufferSize = 2 * audioContext.sampleRate; // 2秒缓冲
                const buffer = audioContext.createBuffer(1, bufferSize, audioContext.sampleRate);
                const data = buffer.getChannelData(0);
                
                // 生成随机信号（白噪音核心）
                for (let i = 0; i < bufferSize; i++) {
                    data[i] = Math.random() * 2 - 1; // -1到1的随机数
                }

                noiseNode = audioContext.createBufferSource();
                noiseNode.buffer = buffer;
                noiseNode.loop = true;
                
                // 添加滤波器控制高频
                const filter = audioContext.createBiquadFilter();
                filter.type = "highpass";
                filter.frequency.value = 1000;
                
                noiseNode.connect(filter);
                filter.connect(analyser);
                analyser.connect(audioContext.destination);
            }

            // 控制播放/暂停
            function toggleNoise() {
                if (!audioContext) initAudio();
                
                if (!isPlaying) {
                    createNoise();
                    noiseNode.start(0);
                    isPlaying = true;
                    requestAnimationFrame(visualize);
                } else {
                    noiseNode.stop();
                    isPlaying = false;
                }
            }

            // 音量控制
            function updateVolume(value) {
                if (noiseNode) noiseNode.gain.value = value;
                document.getElementById('volumeValue').textContent = 
                    Math.round(value * 100) + '%';
            }

 音频可视化
            function visualize() {
                if (!isPlaying) return;

                const canvas = document.querySelector('canvas');
                const ctx = canvas.getContext('2d');
                const bufferLength = analyser.frequencyBinCount;
                const dataArray = new Uint8Array(bufferLength);
                
                analyser.getByteFrequencyData(dataArray);

                ctx.fillStyle = '#f8f9fa';
                ctx.fillRect(0, 0, canvas.width, canvas.height);
                
                // 绘制频谱条
                const barWidth = (canvas.width / bufferLength) * 2.5;
                let x = 0;
                
                for (let i = 0; i < bufferLength; i++) {
                    const barHeight = dataArray[i] / 2;
                    ctx.fillStyle = `hsl(${i * 5}, 70%, 50%)`;
                    ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
                    x += barWidth + 1;
                }

                requestAnimationFrame(visualize);
            }
        </script>
    </div>
</body>
</html>